/*
 * Created on 2005-4-30
 *
 */
package com.hd123.rumba.runtime;

import java.util.Hashtable;
import java.util.Vector;

import org.apache.log4j.Logger;

import com.hd123.rumba.exception.BusinessException;

/**
 * 全局的Observer注册表. 注意: Subject和Observer都是对类的, 所以, observer应该是单实例的.
 * 
 * @author caili
 */
public class ObserverRegistry {

  /**
   * entry = (subjectClass, hasttable of eventEntry) <br>
   * eventEntry = vector of observers (instance)
   */
  public static Hashtable registry = new Hashtable();

  /**
   * 注册observer实例为subjectClass类eventClass类事件的观察者
   * 
   * @param subjectClass
   * @param eventClass
   * @param observer
   */
  public static void register(Class subjectClass, Class eventClass, Object observer)
      throws ClassCastException {
    if (!eventClass.isInstance(observer))
      throw new ClassCastException("observer " + observer + " does not implement " + eventClass);
    Hashtable events = (Hashtable) registry.get(subjectClass);
    if (events == null) {
      events = new Hashtable();
      registry.put(subjectClass, events);
    }
    Vector observers = (Vector) events.get(eventClass);
    if (observers == null) {
      observers = new Vector(1);
      events.put(eventClass, observers);
    }
    if (observers.indexOf(observer) == -1)
      observers.add(observer);
    Logger.getLogger(ObserverRegistry.class).debug(
        observer.getClass().getName() + "已登记响应" + subjectClass.getName() + "的"
            + eventClass.getName() + "事件");
  }

  /**
   * 取消observer实例为subjectClass类eventClass类事件的观察者
   * 
   * @param subjectClass
   * @param eventClass
   * @param observer
   */
  public static void unregister(Class subjectClass, Class eventClass, Object observer) {
    Vector observers = getObservers(subjectClass, eventClass);
    if (observers != null) {
      observers.remove(observer);
    }
  }

  /**
   * 取得subjectClass类eventClass类事件的观察者实例向量
   * 
   * @param subjectClass
   * @param eventClass
   * @return Vector of Object
   */
  public static Vector getObservers(Class subjectClass, Class eventClass) {
    Hashtable events = (Hashtable) registry.get(subjectClass);
    if (events != null) {
      return (Vector) events.get(eventClass);
    } else
      return null;
  }

  /**
   * 通知subjectClass类eventClass类事件的观察者执行事件定义的动作
   * 
   * @param eventClass
   * @param subject
   * @throws BusinessException
   */
  public static void notifyObservers(Class eventClass, Object subject) throws BusinessException {
    doNotifyObservers(eventClass, subject.getClass(), subject);
    Class[] classes = subject.getClass().getInterfaces();
    for (int i = 0; i < classes.length; i++) {
      doNotifyObservers(eventClass, classes[i], subject);
    }
  }

  private static void doNotifyObservers(Class eventClass, Class subjectClass, Object subject)
      throws BusinessException {
    Vector observers = getObservers(subjectClass, eventClass);
    if (observers != null) {
      for (int i = 0; i < observers.size(); ++i) {
        notifyObserver(eventClass, observers.get(i), subject);
      }
    }
  }

  /**
   * 通知observer在subject实例上发生了eventClass事件, 执行相应的动作
   * 
   * @param eventClass
   * @param observer
   * @param subject
   * @throws BusinessException
   */
  public static void notifyObserver(Class eventClass, Object observer, Object subject)
      throws BusinessException {
    if (eventClass.equals(IAfterSaveNew.class)) {
      ((IAfterSaveNew) observer).doAfterSaveNew(subject);
    } else if (eventClass.equals(IBeforeRemove.class)) {
      ((IBeforeRemove) observer).doBeforeRemove(subject);
    } else if (eventClass.equals((IBeforeSave.class))) {
      ((IBeforeSave) observer).doBeforeSave(subject);
    } else if (eventClass.equals(IAfterSave.class)) {
      ((IAfterSave)observer).doAfterSave(subject);
    } else if (eventClass.equals(IAfterLogin.class)) {
      ((IAfterLogin)observer).doAfterLogin(subject);
    } 
  }
}
